import { ArrUtil } from "./ArrUtil";

/**
 * map工具类
 */
export class MapUtil {
	/**
	 * 添加到一个元素到数组map 当map中没有这个key的数组将会创建
	 * @param arrMap
	 * @param key
	 * @param val
	 * @returns 返回这个key的数组
	 */
	static addToArrMap<Val = any, Key = any>(arrMap: Map<Key, Val[]>, key: Key, val: Val) {
		let arr = arrMap.get(key);
		if (arr) {
			arr.push(val);
		} else {
			arrMap.set(key, (arr = [val]));
		}
		return arr;
	}

	/**
	 * 数组map里移除一个元素
	 * @param arrMap
	 * @param key
	 * @param val
	 * @param deleteEmpty 当这个key的数组数量为0时将其移除(默认true)
	 * @returns 返回是否删除了key
	 */
	static removeFromArrMap<Val = any, Key = any>(arrMap: Map<Key, Val[]>, key: Key, val: Val, deleteEmpty = true) {
		const arr = arrMap.get(key);
		if (arr) {
			ArrUtil.remove(arr, val);
			if (deleteEmpty && arr.length === 0) {
				return arrMap.delete(key);
			}
		}
		return false;
	}

	/**
	 * 数组map里移除一个元素
	 * 使用高效数组移除方式,会改变数组的元素次序
	 * @param arrMap
	 * @param key
	 * @param val
	 * @param deleteEmpty 当这个key的数组数量为0时将其移除(默认true)
	 * @returns 返回是否删除了key
	 */
	static removeFastFromArrMap<Val = any, Key = any>(arrMap: Map<Key, Val[]>, key: Key, val: Val, deleteEmpty = true) {
		const arr = arrMap.get(key);
		if (arr) {
			ArrUtil.removeFast(arr, val);
			if (deleteEmpty && arr.length === 0) {
				return arrMap.delete(key);
			}
		}
		return false;
	}

	/**
	 * 添加到一个元素到set map 当map中没有这个key的set将会创建
	 * @param setMap
	 * @param key
	 * @param val
	 */
	static addToSetMap<Val = any, Key = any>(setMap: Map<Key, Set<Val>>, key: Key, val: Val) {
		let set = setMap.get(key);
		if (!set) {
			setMap.set(key, (set = new Set()));
		}
		set.add(val);
		return set;
	}

	/**
	 * set map里移除一个元素
	 * @param setMap
	 * @param key
	 * @param val
	 * @param deleteEmpty  当这个key的set长度为0时将其移除(默认true)
	 * @returns 返回是否删除了key
	 */
	static removeFromSetMap<Val = any, Key = any>(setMap: Map<Key, Set<Val>>, key: Key, val: Val, deleteEmpty = true) {
		const set = setMap.get(key);
		if (set) {
			if (set.delete(val) && deleteEmpty && set.size === 0) {
				return setMap.delete(key);
			}
		}
		return false;
	}

	/**
	 * 从map里面找到符合条件的key
	 * @param map
	 * @param find
	 */
	static findKey<Val = any, Key = any>(map: Map<Key, Val>, find: (val: Val, key: Key) => boolean) {
		const keys = map.keys();
		for (const key of keys) {
			const val = map.get(key);
			if (find(val, key)) {
				return key;
			}
		}
		return null;
	}

	/**
	 * 从map里面找到符合条件的值
	 * @param map
	 * @param find
	 */
	static findVal<Val = any, Key = any>(map: Map<Key, Val>, find: (val: Val, key: Key) => boolean) {
		const keys = map.keys();
		for (const key of keys) {
			const val = map.get(key);
			if (find(val, key)) {
				return val;
			}
		}
		return null;
	}

	/**
	 * 增加number类型map的值
	 * @param map
	 * @param key
	 * @param add
	 * @param defaultVal key没有时的默认值 默认0
	 */
	static addNum(map: Map<any, number>, key: any, add: number, defaultVal = 0) {
		map.set(key, (map.get(key) ?? defaultVal) + add);
	}
}
